//------------------------------------------------------------
//  Filename: pwr_proc.v
//   
//  Author  : wlduan@gmail.com
//  Revise  : 2017-03-07 11:50
//  Description: 
//   
//  Copyright (C) 2014, YRBD, Inc. 					      
//  All Rights Reserved.                                       
//-------------------------------------------------------------
//
`timescale 1ns/1ps
 
module PWR_PROC ( 
    input  wire pl_clk,  

    input  wire force_pwr_off,
    input  wire pwr_touch, 
    output reg  soft_pwr_off, 
    output reg  pwr_ctrl 
);      
//--------------------------------------------------------
wire clk;
reg  rst;
//--------------------------------------------------------
BUFG inst0(
    .I ( pl_clk ),
    .O ( clk    )
);
//--------------------------------------------------------
localparam RESET_TIME = 50000000; //5s
localparam ONE_SECOND = 25000000;//1s
//--------------------------------------------------------
reg [7:0] raw_value0;
reg [7:0] raw_value1;
reg [31:0]reset_cycle;
wire      raw_value0_set = (raw_value0 !== 8'h5A)?1'b1:1'b0;
wire      raw_value1_set = (raw_value1 !== 8'hF0)?1'b1:1'b0;
//--------------------------------------------------------
always @(posedge clk) begin
    if(raw_value0 !== 8'h5A) begin 
        raw_value0 <= 8'h5A;    
    end 
end 
//--------------------------------------------------------
always @(posedge clk) begin
    if(raw_value1 !== 8'hF0) begin 
        raw_value1 <= 8'hF0;    
    end 
end 
//--------------------------------------------------------
always @(posedge clk) begin
    if(raw_value0_set||raw_value1_set)begin 
        reset_cycle <= 0;    
    end 
    else if(reset_cycle < RESET_TIME ) begin 
        reset_cycle <= reset_cycle + 1;     
    end 
end 
//--------------------------------------------------------
always @(posedge clk) begin
    if(raw_value0_set||raw_value1_set||(reset_cycle < RESET_TIME))begin 
        rst <= 1;    
    end 
    else begin 
        rst <= 0;  
    end 
end 
//--------------------------------------------------------
reg[31:0] pwr_ctrl_counter;
always @(posedge clk) begin
    if(rst)begin 
        pwr_ctrl_counter <= 32'b0;
    end
    else begin
        pwr_ctrl_counter <= (pwr_ctrl_counter < ONE_SECOND)?(pwr_ctrl_counter + 32'b1):32'b0;
    end
end
//--------------------------------------------------------
reg pwr_ctrl_pulse;
always @(posedge clk) pwr_ctrl_pulse <= (pwr_ctrl_counter < ONE_SECOND)?1'b0:1'b1;
//--------------------------------------------------------
reg[31:0] pwr_ctrl_s;
//--------------------------------------------------------
always @(posedge clk) begin
    if(rst)begin  
        pwr_ctrl_s <= 32'b0;
    end
    else if (pwr_touch == 1'b1) begin
        pwr_ctrl_s <= 32'b0;
    end
    else if(pwr_ctrl_pulse)begin  
        pwr_ctrl_s <= pwr_ctrl_s + 32'b1;
    end    
end
//--------------------------------------------------------
reg[31:0] pwr_ctrl_r;
//--------------------------------------------------------
always @(posedge clk) begin
    if(rst)begin  
        pwr_ctrl_r <= 32'b0;
    end
    else if(pwr_ctrl_pulse&&(pwr_ctrl_r < 6))begin  
        pwr_ctrl_r <= pwr_ctrl_r + 32'b1;
    end    
end
//--------------------------------------------------------
reg start_up;
//--------------------------------------------------------
always @(posedge clk) begin
    if(rst)begin  
        start_up <= 1'b0;
    end
    else begin  
        start_up <= (pwr_ctrl_r < 6)?1'b0:1'b1;
    end    
end
//--------------------------------------------------------
always @(posedge clk) begin
    if(rst)begin 
        soft_pwr_off <= 1'b0;
    end    
    else if(start_up&&((pwr_ctrl_s > 1)||force_pwr_off)) begin
        soft_pwr_off <= 1'b1;
    end
end
//--------------------------------------------------------
reg[31:0] pwr_ctrl_t;
//--------------------------------------------------------
always @(posedge clk) begin
    if(rst)begin 
        pwr_ctrl_t <= 32'b0;
    end
    else if(pwr_ctrl_pulse&&soft_pwr_off) begin
        pwr_ctrl_t <= pwr_ctrl_t + 32'b1;
    end  
end
//--------------------------------------------------------
wire PWR_OFF = 0; 
//wire PWR_OFF = 1; // FUSION_V1
//--------------------------------------------------------
always @(posedge clk) begin
    if(rst)begin 
        pwr_ctrl <= ~PWR_OFF;
    end
    else if(pwr_ctrl_t < 2) begin
        pwr_ctrl <= ~PWR_OFF;
    end
    else begin
        pwr_ctrl <= PWR_OFF;
    end
end

endmodule
